namespace SubhadraSolutions.Sharp.Logging
{
    using SubhadraSolutions.Sharp.Logging.Contracts;
    using SubhadraSolutions.Sharp.Utils;
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Threading;

    [Serializable]
    public class LogStoreItem : ILogItem
    {
        #region Fields

        private SortedDictionary<string, object> _globalContextValues;

        #endregion Fields

        #region Constructors

        static LogStoreItem()
        {
            var logEntryTypesToStrings = new string[6];
            logEntryTypesToStrings[(int)LogItemSeverity.DEBUG] = LogItemSeverity.DEBUG.ToString();
            logEntryTypesToStrings[(int)LogItemSeverity.ERROR] = LogItemSeverity.ERROR.ToString();
            logEntryTypesToStrings[(int)LogItemSeverity.FATAL] = LogItemSeverity.FATAL.ToString();
            logEntryTypesToStrings[(int)LogItemSeverity.INFO] = LogItemSeverity.INFO.ToString();
            logEntryTypesToStrings[(int)LogItemSeverity.WARN] = LogItemSeverity.WARN.ToString();
        }

        public LogStoreItem(LogItemSeverity severity, LogItemCategories categories, object logEntry)
            : this()
        {
            Severity = severity;
            Categories = categories;
            LogEntry = logEntry;
        }

        protected LogStoreItem()
        {
            TimeStamp = GlobalSettings.Instance.CurrentDateTime;
            ThreadId = Thread.CurrentThread.ManagedThreadId;
            ThreadName = Thread.CurrentThread.Name;
        }

        #endregion Constructors

        #region Properties

        public SortedDictionary<string, object> ContextValues
        {
            get { return _globalContextValues; }
            set { _globalContextValues = value; }
        }

        //public string ContextValuesAsString
        //{
        //    get
        //    {
        //        var writer = new StringWriter();
        //        WriteContextValuesToWriter(writer);
        //        return writer.ToString();
        //    }
        //}

        public object LogEntry
        {
            get;
            protected set;
        }

        public LogItemSeverity Severity
        {
            get;
            protected set;
        }

        public LogItemCategories Categories
        {
            get;
            protected set;
        }

        public int ThreadId
        {
            get;
            protected set;
        }

        public string ThreadName
        {
            get;
            protected set;
        }

        public DateTime TimeStamp
        {
            get;
            protected set;
        }

        #endregion Properties

        #region Methods

        public override string ToString()
        {
            var writer = new StringWriter();
            WriteToWriter(writer);
            return writer.ToString();
        }

        public void WriteContextValuesToWriter(TextWriter writer)
        {
            if (ContextValues == null)
            {
                return;
            }
            int count = ContextValues.Count;
            if (count == 0)
            {
                return;
            }
            int i = 0;
            foreach (var item in ContextValues)
            {
                writer.Write(item.Key);
                writer.Write('=');
                writer.Write(item.Value);
                i++;
                if (i < count)
                {
                    writer.Write('\t');
                }
            }
        }


        public void WriteToWriter(TextWriter writer)
        {
            writer.Write('[');
            //writer.Write(_logEntryTypesToStrings[(int)this.LogEntryType]);
            writer.Write(Severity.ToString());
            writer.Write('\t');
            writer.Write(Categories.ToString());
            writer.Write('\t');
            writer.Write(StringHelper.ConvertDateTimeToString(TimeStamp));
            writer.Write('\t');
            writer.Write(ThreadId.ToString(CultureInfo.InvariantCulture));
            if (ThreadName != null)
            {
                writer.Write('\t');
                writer.Write(ThreadName);
            }
            writer.Write("]\t[");
            WriteContextValuesToWriter(writer);
            writer.Write("]\t[");
            writer.Write(LogEntry);
            writer.Write("]");
        }

        #endregion Methods
    }
}